home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / distutils / fancy_getopt.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  12KB  |  387 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''distutils.fancy_getopt
  5.  
  6. Wrapper around the standard getopt module that provides the following
  7. additional features:
  8.   * short and long options are tied together
  9.   * options have help strings, so fancy_getopt could potentially
  10.     create a complete usage summary
  11.   * options set attributes of a passed-in object
  12. '''
  13. __revision__ = '$Id: fancy_getopt.py,v 1.30 2004/11/10 22:23:14 loewis Exp $'
  14. import sys
  15. import string
  16. import re
  17. from types import *
  18. import getopt
  19. from distutils.errors import *
  20. longopt_pat = '[a-zA-Z](?:[a-zA-Z0-9-]*)'
  21. longopt_re = re.compile('^%s$' % longopt_pat)
  22. neg_alias_re = re.compile('^(%s)=!(%s)$' % (longopt_pat, longopt_pat))
  23. longopt_xlate = string.maketrans('-', '_')
  24.  
  25. class FancyGetopt:
  26.     '''Wrapper around the standard \'getopt()\' module that provides some
  27.     handy extra functionality:
  28.       * short and long options are tied together
  29.       * options have help strings, and help text can be assembled
  30.         from them
  31.       * options set attributes of a passed-in object
  32.       * boolean options can have "negative aliases" -- eg. if
  33.         --quiet is the "negative alias" of --verbose, then "--quiet"
  34.         on the command line sets \'verbose\' to false
  35.     '''
  36.     
  37.     def __init__(self, option_table = None):
  38.         self.option_table = option_table
  39.         self.option_index = { }
  40.         if self.option_table:
  41.             self._build_index()
  42.         
  43.         self.alias = { }
  44.         self.negative_alias = { }
  45.         self.short_opts = []
  46.         self.long_opts = []
  47.         self.short2long = { }
  48.         self.attr_name = { }
  49.         self.takes_arg = { }
  50.         self.option_order = []
  51.  
  52.     
  53.     def _build_index(self):
  54.         self.option_index.clear()
  55.         for option in self.option_table:
  56.             self.option_index[option[0]] = option
  57.         
  58.  
  59.     
  60.     def set_option_table(self, option_table):
  61.         self.option_table = option_table
  62.         self._build_index()
  63.  
  64.     
  65.     def add_option(self, long_option, short_option = None, help_string = None):
  66.         if self.option_index.has_key(long_option):
  67.             raise DistutilsGetoptError, "option conflict: already an option '%s'" % long_option
  68.         else:
  69.             option = (long_option, short_option, help_string)
  70.             self.option_table.append(option)
  71.             self.option_index[long_option] = option
  72.  
  73.     
  74.     def has_option(self, long_option):
  75.         """Return true if the option table for this parser has an
  76.         option with long name 'long_option'."""
  77.         return self.option_index.has_key(long_option)
  78.  
  79.     
  80.     def get_attr_name(self, long_option):
  81.         """Translate long option name 'long_option' to the form it
  82.         has as an attribute of some object: ie., translate hyphens
  83.         to underscores."""
  84.         return string.translate(long_option, longopt_xlate)
  85.  
  86.     
  87.     def _check_alias_dict(self, aliases, what):
  88.         if not type(aliases) is DictionaryType:
  89.             raise AssertionError
  90.         for alias, opt in aliases.items():
  91.             if not self.option_index.has_key(alias):
  92.                 raise DistutilsGetoptError, "invalid %s '%s': option '%s' not defined" % (what, alias, alias)
  93.             
  94.             if not self.option_index.has_key(opt):
  95.                 raise DistutilsGetoptError, "invalid %s '%s': aliased option '%s' not defined" % (what, alias, opt)
  96.                 continue
  97.         
  98.  
  99.     
  100.     def set_aliases(self, alias):
  101.         '''Set the aliases for this option parser.'''
  102.         self._check_alias_dict(alias, 'alias')
  103.         self.alias = alias
  104.  
  105.     
  106.     def set_negative_aliases(self, negative_alias):
  107.         """Set the negative aliases for this option parser.
  108.         'negative_alias' should be a dictionary mapping option names to
  109.         option names, both the key and value must already be defined
  110.         in the option table."""
  111.         self._check_alias_dict(negative_alias, 'negative alias')
  112.         self.negative_alias = negative_alias
  113.  
  114.     
  115.     def _grok_option_table(self):
  116.         """Populate the various data structures that keep tabs on the
  117.         option table.  Called by 'getopt()' before it can do anything
  118.         worthwhile.
  119.         """
  120.         self.long_opts = []
  121.         self.short_opts = []
  122.         self.short2long.clear()
  123.         self.repeat = { }
  124.         for option in self.option_table:
  125.             if len(option) == 3:
  126.                 (long, short, help) = option
  127.                 repeat = 0
  128.             elif len(option) == 4:
  129.                 (long, short, help, repeat) = option
  130.             else:
  131.                 raise ValueError, 'invalid option tuple: %r' % (option,)
  132.             if type(long) is not StringType or len(long) < 2:
  133.                 raise DistutilsGetoptError, "invalid long option '%s': must be a string of length >= 2" % long
  134.             
  135.             if not short is None and type(short) is StringType and len(short) == 1:
  136.                 raise DistutilsGetoptError, "invalid short option '%s': must a single character or None" % short
  137.             
  138.             self.repeat[long] = repeat
  139.             self.long_opts.append(long)
  140.             if long[-1] == '=':
  141.                 if short:
  142.                     short = short + ':'
  143.                 
  144.                 long = long[0:-1]
  145.                 self.takes_arg[long] = 1
  146.             else:
  147.                 alias_to = self.negative_alias.get(long)
  148.                 if alias_to is not None:
  149.                     if self.takes_arg[alias_to]:
  150.                         raise DistutilsGetoptError, "invalid negative alias '%s': aliased option '%s' takes a value" % (long, alias_to)
  151.                     
  152.                     self.long_opts[-1] = long
  153.                     self.takes_arg[long] = 0
  154.                 else:
  155.                     self.takes_arg[long] = 0
  156.             alias_to = self.alias.get(long)
  157.             if alias_to is not None:
  158.                 if self.takes_arg[long] != self.takes_arg[alias_to]:
  159.                     raise DistutilsGetoptError, "invalid alias '%s': inconsistent with aliased option '%s' (one of them takes a value, the other doesn't" % (long, alias_to)
  160.                 
  161.             
  162.             if not longopt_re.match(long):
  163.                 raise DistutilsGetoptError, ("invalid long option name '%s' " + '(must be letters, numbers, hyphens only') % long
  164.             
  165.             self.attr_name[long] = self.get_attr_name(long)
  166.             if short:
  167.                 self.short_opts.append(short)
  168.                 self.short2long[short[0]] = long
  169.                 continue
  170.         
  171.  
  172.     
  173.     def getopt(self, args = None, object = None):
  174.         """Parse command-line options in args. Store as attributes on object.
  175.  
  176.         If 'args' is None or not supplied, uses 'sys.argv[1:]'.  If
  177.         'object' is None or not supplied, creates a new OptionDummy
  178.         object, stores option values there, and returns a tuple (args,
  179.         object).  If 'object' is supplied, it is modified in place and
  180.         'getopt()' just returns 'args'; in both cases, the returned
  181.         'args' is a modified copy of the passed-in 'args' list, which
  182.         is left untouched.
  183.         """
  184.         if args is None:
  185.             args = sys.argv[1:]
  186.         
  187.         if object is None:
  188.             object = OptionDummy()
  189.             created_object = 1
  190.         else:
  191.             created_object = 0
  192.         self._grok_option_table()
  193.         short_opts = string.join(self.short_opts)
  194.         
  195.         try:
  196.             (opts, args) = getopt.getopt(args, short_opts, self.long_opts)
  197.         except getopt.error:
  198.             msg = None
  199.             raise DistutilsArgError, msg
  200.  
  201.         for opt, val in opts:
  202.             if len(opt) == 2 and opt[0] == '-':
  203.                 opt = self.short2long[opt[1]]
  204.             elif not len(opt) > 2 or opt[:2] == '--':
  205.                 raise AssertionError
  206.             opt = opt[2:]
  207.             alias = self.alias.get(opt)
  208.             if alias:
  209.                 opt = alias
  210.             
  211.             if not self.takes_arg[opt]:
  212.                 if not val == '':
  213.                     raise AssertionError, "boolean option can't have value"
  214.                 alias = self.negative_alias.get(opt)
  215.                 if alias:
  216.                     opt = alias
  217.                     val = 0
  218.                 else:
  219.                     val = 1
  220.             
  221.             attr = self.attr_name[opt]
  222.             if val and self.repeat.get(attr) is not None:
  223.                 val = getattr(object, attr, 0) + 1
  224.             
  225.             setattr(object, attr, val)
  226.             self.option_order.append((opt, val))
  227.         
  228.         if created_object:
  229.             return (args, object)
  230.         else:
  231.             return args
  232.  
  233.     
  234.     def get_option_order(self):
  235.         """Returns the list of (option, value) tuples processed by the
  236.         previous run of 'getopt()'.  Raises RuntimeError if
  237.         'getopt()' hasn't been called yet.
  238.         """
  239.         if self.option_order is None:
  240.             raise RuntimeError, "'getopt()' hasn't been called yet"
  241.         else:
  242.             return self.option_order
  243.  
  244.     
  245.     def generate_help(self, header = None):
  246.         '''Generate help text (a list of strings, one per suggested line of
  247.         output) from the option table for this FancyGetopt object.
  248.         '''
  249.         max_opt = 0
  250.         for option in self.option_table:
  251.             long = option[0]
  252.             short = option[1]
  253.             l = len(long)
  254.             if long[-1] == '=':
  255.                 l = l - 1
  256.             
  257.             if short is not None:
  258.                 l = l + 5
  259.             
  260.             if l > max_opt:
  261.                 max_opt = l
  262.                 continue
  263.         
  264.         opt_width = max_opt + 2 + 2 + 2
  265.         line_width = 78
  266.         text_width = line_width - opt_width
  267.         big_indent = ' ' * opt_width
  268.         if header:
  269.             lines = [
  270.                 header]
  271.         else:
  272.             lines = [
  273.                 'Option summary:']
  274.         for option in self.option_table:
  275.             (long, short, help) = option[:3]
  276.             text = wrap_text(help, text_width)
  277.             if long[-1] == '=':
  278.                 long = long[0:-1]
  279.             
  280.             if short is None:
  281.                 if text:
  282.                     lines.append('  --%-*s  %s' % (max_opt, long, text[0]))
  283.                 else:
  284.                     lines.append('  --%-*s  ' % (max_opt, long))
  285.             else:
  286.                 opt_names = '%s (-%s)' % (long, short)
  287.                 if text:
  288.                     lines.append('  --%-*s  %s' % (max_opt, opt_names, text[0]))
  289.                 else:
  290.                     lines.append('  --%-*s' % opt_names)
  291.             for l in text[1:]:
  292.                 lines.append(big_indent + l)
  293.             
  294.         
  295.         return lines
  296.  
  297.     
  298.     def print_help(self, header = None, file = None):
  299.         if file is None:
  300.             file = sys.stdout
  301.         
  302.         for line in self.generate_help(header):
  303.             file.write(line + '\n')
  304.         
  305.  
  306.  
  307.  
  308. def fancy_getopt(options, negative_opt, object, args):
  309.     parser = FancyGetopt(options)
  310.     parser.set_negative_aliases(negative_opt)
  311.     return parser.getopt(args, object)
  312.  
  313. WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace))
  314.  
  315. def wrap_text(text, width):
  316.     """wrap_text(text : string, width : int) -> [string]
  317.  
  318.     Split 'text' into multiple lines of no more than 'width' characters
  319.     each, and return the list of strings that results.
  320.     """
  321.     if text is None:
  322.         return []
  323.     
  324.     if len(text) <= width:
  325.         return [
  326.             text]
  327.     
  328.     text = string.expandtabs(text)
  329.     text = string.translate(text, WS_TRANS)
  330.     chunks = re.split('( +|-+)', text)
  331.     chunks = filter(None, chunks)
  332.     lines = []
  333.     while chunks:
  334.         cur_line = []
  335.         cur_len = 0
  336.         while chunks:
  337.             l = len(chunks[0])
  338.             if cur_len + l <= width:
  339.                 cur_line.append(chunks[0])
  340.                 del chunks[0]
  341.                 cur_len = cur_len + l
  342.                 continue
  343.             if cur_line and cur_line[-1][0] == ' ':
  344.                 del cur_line[-1]
  345.             
  346.             break
  347.         if chunks:
  348.             if cur_len == 0:
  349.                 cur_line.append(chunks[0][0:width])
  350.                 chunks[0] = chunks[0][width:]
  351.             
  352.             if chunks[0][0] == ' ':
  353.                 del chunks[0]
  354.             
  355.         
  356.         lines.append(string.join(cur_line, ''))
  357.     return lines
  358.  
  359.  
  360. def translate_longopt(opt):
  361.     '''Convert a long option name to a valid Python identifier by
  362.     changing "-" to "_".
  363.     '''
  364.     return string.translate(opt, longopt_xlate)
  365.  
  366.  
  367. class OptionDummy:
  368.     '''Dummy class just used as a place to hold command-line option
  369.     values as instance attributes.'''
  370.     
  371.     def __init__(self, options = []):
  372.         """Create a new OptionDummy instance.  The attributes listed in
  373.         'options' will be initialized to None."""
  374.         for opt in options:
  375.             setattr(self, opt, None)
  376.         
  377.  
  378.  
  379. if __name__ == '__main__':
  380.     text = 'Tra-la-la, supercalifragilisticexpialidocious.\nHow *do* you spell that odd word, anyways?\n(Someone ask Mary -- she\'ll know [or she\'ll\nsay, "How should I know?"].)'
  381.     for w in (10, 20, 30, 40):
  382.         print 'width: %d' % w
  383.         print string.join(wrap_text(text, w), '\n')
  384.         print 
  385.     
  386.  
  387.